Header file downcast.hpp

namespace type_safe
{
    template <typename T>
    struct derived_type;
    
    namespace detail
    {
        template <typename T>
        bool is_safe_downcast(derived_type<T>, const T&);
        
        template <typename Derived, typename Base>
        typename std::enable_if<std::is_polymorphic<Base>::value, bool>::type is_safe_downcast(derived_type<Derived>, const Base& obj);
        
        template <typename Derived, typename Base>
        typename std::enable_if<!std::is_polymorphic<Base>::value, bool>::type is_safe_downcast(derived_type<Derived>, const Base&);
        
        template <typename Derived, typename Base>
        void validate_downcast(const Base& obj) noexcept;
    }
    
    template <typename Derived, typename Base>
    Derived downcast(Base& obj) noexcept;
    
    template <typename Derived, typename Base>
    Derived& downcast(derived_type<Derived>, Base& obj) noexcept;
    template <typename Derived, typename Base>
    const Derived& downcast(derived_type<Derived>, const Base& obj) noexcept;
}

Class template type_safe::derived_type

template <typename T>
struct derived_type
{
};

Tag type to specify the derived type of a ts::downcast.

Pass it as first parameter to the appropriate overload.

Function template type_safe::downcast

template <typename Derived, typename Base>
Derived downcast(Base& obj) noexcept;

Casts an object of base class type to the derived class type.

Returns: The object converted as if static_cast<Derived>(obj).

Requires: Base must be a base class of Derived, and the dynamic type of obj must be Derived.

Function template type_safe::downcast

(1)  template <typename Derived, typename Base>
     Derived& downcast(derived_type<Derived>, Base& obj) noexcept;

(2)  template <typename Derived, typename Base>
     const Derived& downcast(derived_type<Derived>, const Base& obj) noexcept;

Casts an object of base class type to the derived class type.

Returns: The object converted as if static_cast<derived_ref>(obj), where derived_ref is the type of Derived with matching qualifiers.

Requires: Base must be a base class of Derived, and the dynamic type of obj must be Derived.